from flask import Blueprint, render_template, redirect, request
from .apis import Apis
import json
import time
import os
from socket import *
import subprocess
import configparser

import sys
import math
import struct

from .broker import Broker
from .cdb import CDB
from .flash import Flash
from .cmis import CMIS

from .crc import crc32
from .hwinfo import HWInfo

import threading
from queue import Queue

# here define a route
host_bp = Blueprint(
    'host',
    '__name__',
)

a = Apis()
for_customer = a.is_for_customer()

##################################################
# SETTINGS
##################################################
@host_bp.route('/')
@host_bp.route('/settings')
def settings():
    return render_template('settings.html', title='Settings', for_customer=for_customer)


@host_bp.route('/api/get_settings')
def get_settings():
    settings1_dict = {}
    try:
        settings1_dict.update({'connect_status': 'on'})
        settings1_dict.update({'ip_id': a.get_ip()})
        settings1_dict.update({'mac': a.get_mac()})
        settings1_dict.update({'sn_id': a.get_sn()})
        settings1_dict.update(
            {'board_type': a.read_item_from_config_ini('dev', 'product')})

        # settings1_dict.update( { 'fw_id' : a.get_fw_ver() } )

        # settings1_dict.update( { 'gui_id' : '3.0.0_20190905' } )
        settings1_dict.update(
            {'gui_id': a.read_item_from_config_ini('gui', 'version')})

        settings1_dict.update({'server_name': a.server_name()})
        settings1_dict.update({'server_ip': a.server_ip()})
        settings1_dict.update({'server_port': a.server_port()})
    except:
        settings1_dict.update({'connect_status': 'off'})

    # print('-------------------------')
    # print(str(settings1_dict))
    # print('-------------------------')
    return json.dumps(settings1_dict)


@host_bp.route('/api/set_device_sn', methods=['POST'])
def set_device_sn():
    sn_val = request.form["sn_val"]
    a.set_sn(sn_val)
    # print("set_device_sn... ok")
    return "set_device_sn... ok"


@host_bp.route('/api/set_board_type', methods=['POST'])
def set_board_type():
    board_type = request.form["board_type"]
    print(board_type)
    a.write_item_to_config_ini('dev', 'product', board_type)
    # a.set_sn(sn_val)
    # print("set_device_sn... ok")
    return "board_type... ok"


@host_bp.route('/api/set_device_ip', methods=['POST'])
def set_device_ip():
    ip_val = request.form["ip_val"]
    # save to config ini file
    a.write_item_to_config_ini('dev', 'ip', ip_val)
    # call cmd set to host
    a.comm_cmdstr_setter('*IP ' + ip_val)
    return "set_device_ip... ok"


@host_bp.route('/api/set_mac_address', methods=['POST'])
def set_mac_address():
    mac3_val = request.form["mac3"]
    mac4_val = request.form["mac4"]
    mac5_val = request.form["mac5"]

    a.comm_cmdstr_setter('*mac ' + mac3_val + " " + mac4_val + " " + mac5_val)
    return "set_mac_address... ok"


@host_bp.route('/api/get_host_fw_ver')
def get_host_fw_ver():
    fw_ver = a.get_fw_ver()
    return fw_ver


@host_bp.route('/api/btn_reconnect', methods=['POST'])
def btn_reconnect():
    os.system("Reload.bat")
    return "btn_reconnect... ok"


@host_bp.route('/api/btn_writeconfig_and_reconnect', methods=['POST'])
def btn_writeconfig_and_reconnect():
    ip_val = request.form["ip_val"]
    # save to config ini file
    a.write_item_to_config_ini('dev', 'ip', ip_val)

    # restart GUI
    os.system("Reload.bat")
    return "btn_writeconfig_and_reconnect... ok"


# when page10h:145 is 0x10，set page10h:143=0xff (set application mode 1x400GE)
# when page10h:145 is 0x20，set page10h:143=0xff (set application mode 4x100GE)
# when page10h:180 is 0x10，set page10h:178=0xff (set application mode 1x400GE)
# when page10h:180 is 0x20，set page10h:178=0xff (set application mode 4x100GE) 
@host_bp.route('/api/set_app_mode', methods=['POST'])
def set_app_mode():
    app_mode = request.form["app_mode"]
    print("set app_mode: ", app_mode)
    a.set_twi(1, 127, 0x10)
    ret1 = a.get_twi(1, 145).split(',')[0]
    ret2 = a.get_twi(1, 180).split(',')[0]
    print(ret1) #hex
    print(ret2) #hex

    if app_mode == "1x400GE":
        if ret1 == '10':
            a.set_twi(1, 143, 0xff)
        elif ret2 == '10':
            a.set_twi(1, 178, 0xff)
        else:
            print("set application error!")
    else: #4x100GE
        if ret1 == '20':
            a.set_twi(1, 143, 0xff)
        elif ret2 == '20':
            a.set_twi(1, 178, 0xff)
        else:
            print("set application error!")
    return "set_app_mode: ok"


# save是通过pageB0h:255.b0 = 1来设置的，设置之前需要写密码
@host_bp.route('/api/save_app_mode', methods=['POST'])
def save_app_mode():
    b = Broker()
    b.cdb_psw()
    a.set_twi(1, 127, 0xb0)
    a.set_twi(1, 255, 0x1)
    time.sleep(2)
    return "save_app_mode: ok"


@host_bp.route('/api/btn_get_current_active_application')
def btn_get_current_active_application():
    # Read current active application by page11:206-213
    # Page11:206-213 = [0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10]: 1X400GE 400ZR
    # Page11:206-213 = [0x20, 0x20, 0x24, 0x24, 0x28, 0x28, 0x2c, 0x2c]: 4X100GE 400ZR
    data = []
    a.set_twi(1, 127, 0x11)

    for i in range(206, 214):
        ret = a.get_twi(1, i).split(',')[0]  #hex
        data.append(int('0x'+ret, 16))
    
    print('btn_get_current_active_application ...')
    print(data)

    if data == [0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10]:
        return "1X400GE 400ZR"
    elif data == [0x20, 0x20, 0x24, 0x24, 0x28, 0x28, 0x2c, 0x2c]:
        return "4X100GE 400ZR"
    else:
        return "---"


@host_bp.route('/api/btn_get_mod_info')
def btn_get_mod_info():
    b = Broker()
    # b.IP = arguments.portal
    cdb = CDB(b)
    cmis = CMIS(b)
    hw = HWInfo(b)
    
    # epoch = time.time()
    # sys.stdout.write('Read Image Info...\n')
    ret_txt = ''
    tmp_txt = ''
    rlplen, rlp_chkcode, rlp = cdb.CMD0100h()
    if b.cdb_chkcode(rlp) == rlp_chkcode:
        fwStaus = rlp[0]  #136
        tmp_txt = ('<tr><td>Image A Running </td><td> %d</td></tr>' % (fwStaus & 0x01))  #bit0
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Image A Commited </td><td> %d</td></tr>' % ((fwStaus >> 1) & 0x01)
                   )  #bit1
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Image A Empty </td><td> %d</td></tr>' % ((fwStaus >> 2) & 0x01))  #bit2
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Image B Running </td><td> %d</td></tr>' % ((fwStaus >> 4) & 0x01)
                   )  #bit4
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Image B Commited </td><td> %d</td></tr>' % ((fwStaus >> 5) & 0x01)
                   )  #bit5
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Image B Empty </td><td> %d</td></tr>' % ((fwStaus >> 6) & 0x01))  #bit6
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Image A Version </td><td> %d.%d</td></tr>' % (rlp[2], rlp[3]))  #138,139
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Image A BuildNum </td><td> %d</td></tr>' % ((rlp[4] << 8) | rlp[5])
                   )  #140,141
        ret_txt += tmp_txt

        sub_mcu_imageA_ver = struct.unpack('>I', rlp[6:10])[0]  #142-145
        tmp_txt = ('<tr><td>Sub MCU Image A Ver </td><td> %08x <b class=b1>(%s)</b></td></tr>' % (sub_mcu_imageA_ver, a.dot_split_style_version1(sub_mcu_imageA_ver)) )  #142-145
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Sub MCU Running Img </td><td> %d</td></tr>' % rlp[10])  #146
        ret_txt += tmp_txt

        dsp_imageA_ver = struct.unpack('>I', rlp[11:15])[0]  #147-150
        tmp_txt = ('<tr><td>DSP Image A Ver </td><td> %08x <b class=b1>(%s)</b></td></tr>' % (dsp_imageA_ver, a.dot_split_style_version(dsp_imageA_ver)) )  #147-150
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Image B Version </td><td> %d.%d</td></tr>' %
                   (rlp[174 - 136], rlp[175 - 136]))  #174,175
        ret_txt += tmp_txt

        tmp_txt = ('<tr><td>Image B BuildNum </td><td> %d</td></tr>' %
                   ((rlp[176 - 136] << 8) | rlp[177 - 136]))  #176,177
        ret_txt += tmp_txt

        sub_mcu_imageB_ver = struct.unpack(
            '>I', rlp[(178 - 136):(182 - 136)])[0]  #178-181
        tmp_txt = ('<tr><td>Sub MCU Image B Ver </td><td> %08x <b class=b1>(%s)</b></td></tr>' % (sub_mcu_imageB_ver, a.dot_split_style_version1(sub_mcu_imageB_ver)) )  #178-181
        ret_txt += tmp_txt

        dsp_imageB_ver = struct.unpack(
            '>I', rlp[(182 - 136):(186 - 136)])[0]  #182-185
        tmp_txt = ('<tr><td>DSP Image B Ver </td><td> %08x <b class=b1>(%s)</b></td></tr>' % (dsp_imageB_ver, a.dot_split_style_version(dsp_imageB_ver)) )  #182-185
        ret_txt += tmp_txt

        b.cdb_psw()
        print(cmis.cfg_ver)
        cmis_config_ver = str(cmis.cfg_ver["Major"]) + "." + str(cmis.cfg_ver["Minor"])
        tmp_txt = ('<tr><td>Module Config Table Ver </td><td> <b class=b1>(%s)</b></td></tr>' % ( cmis_config_ver ) ) 
        ret_txt += tmp_txt
        #-------------------------------------------------------------------------------
        a.set_twi(1, 127, 0x00)
        # 129-144 16 Vendor name Vendor name (ASCII)
        vn = ''
        for i in range(129, 145):
            ret = a.get_twi(1, i).split(',')[0]  #hex
            vn = vn + chr( int('0x' + str(ret), 16) )
        tmp_txt = ('<tr><td>Vendor Name</td><td> <b class=b1>%s</b></td></tr>' % vn )
        ret_txt += tmp_txt

        # 148-163 16 Vendor PN Part number provided by vendor (ASCII)
        vpn = ''
        for i in range(148, 164):
            ret = a.get_twi(1, i).split(',')[0]  #hex
            vpn = vpn + chr( int('0x' + str(ret), 16) )
        tmp_txt = ('<tr><td>Vendor PN</td><td> <b class=b1>%s</b></td></tr>' % vpn )
        ret_txt += tmp_txt

        # 164-165 2 Vendor rev Revision level for part number provided by vendor (ASCII)
        # vrev = ''
        # for i in range(164, 166):
        #     ret = a.get_twi(1, i).split(',')[0]  #hex
        #     vrev = vrev + chr( int('0x' + str(ret), 16) )
        # tmp_txt = ('Vendor Rev: <b class=b1>%s</b> <br>' % vrev )
        # ret_txt += tmp_txt

        # 166-181 16 Vendor SN Vendor Serial Number (ASCII)
        vsn = ''
        for i in range(166, 182):
            ret = a.get_twi(1, i).split(',')[0]  #hex
            vsn = vsn + chr( int('0x' + str(ret), 16) )
        tmp_txt = ('<tr><td>Vendor Serial Number</td><td> <b class=b1>%s</b></td></tr>' % vsn )
        ret_txt += tmp_txt
    else:
        tmp_txt = ('<tr><td clospan=5>Rlp check code Err...</td></tr>')
        ret_txt += tmp_txt


    # get hw info-------------------------------------------------------------
    # b.cdb_psw()
    # flash = Flash(b)
    # startAddr = 0x308000
    # sectorNo = int(startAddr / 4096)

    # readRes = b''
    # data_len = a.read_item_from_config_ini('dev','module_config_file_len')
    # if data_len == '---':
    #     pass
    # else:
    #     remaining = int(data_len)
    #     readout = 0
    #     BLOCK_SIZE = 128
    #     while remaining:
    #         if remaining >= BLOCK_SIZE:
    #             res = flash.read(startAddr+readout, BLOCK_SIZE)
    #             readRes += struct.pack('%sB'%len(res), *res)
    #             readout += BLOCK_SIZE
    #             remaining -= BLOCK_SIZE
    #         else:
    #             res = flash.read(startAddr+readout, remaining)
    #             readRes += struct.pack('%sB'%len(res), *res)
    #             readout += remaining
    #             remaining -= remaining
    #     # print(readRes)

    #     flash_data = ''.join(['%04X ' %x  for x in readRes])
    #     # print("DATA: {}".format(flash_data))
    #     fdl = flash_data.split(" ")

    #     tmp_txt = ('<tr><td clospan=5><b>Hardware Info</b></td></tr>' )
    #     ret_txt += tmp_txt
    #     tmp_txt = ('<tr><td>PCBM Version</td><td><b class=b1>%s</b> </td></tr>' % str(int('0x' + fdl[19] + fdl[18]+ fdl[17]+ fdl[16], 16)) )
    #     ret_txt += tmp_txt
    #     tmp_txt = ('<tr><td>PCBS Version</td><td><b class=b1>%s</b> </td></tr>' % str(int('0x' + fdl[23] + fdl[22]+ fdl[21]+ fdl[20], 16)) )
    #     ret_txt += tmp_txt
    #     tmp_txt = ('<tr><td>DSP Version</td><td><b class=b1>%s</b> </td></tr>' % str(int('0x' + fdl[27] + fdl[26]+ fdl[25]+ fdl[24], 16)) )
    #     ret_txt += tmp_txt
    #     tmp_txt = ('<tr><td>COSA Version</td><td><b class=b1>%s</b> </td></tr>' % str(int('0x' + fdl[31] + fdl[30]+ fdl[29]+ fdl[28], 16)) )
    #     ret_txt += tmp_txt
    #     tmp_txt = ('<tr><td>ITLA Version</td><td><b class=b1>%s</b> </td></tr>' % str(int('0x' + fdl[35] + fdl[34]+ fdl[33]+ fdl[32], 16)) )
    #     ret_txt += tmp_txt

    hw.load()
    tmp_txt = ('<tr><td clospan=5><b>Hardware Info</b></td></tr>' )
    ret_txt += tmp_txt
    tmp_txt = ('<tr><td>PCBM Version</td><td><b class=b1>{}</b> </td></tr>'.format(hw.HWInfo['PCBM_Version']) )
    ret_txt += tmp_txt
    tmp_txt = ('<tr><td>PCBS Version</td><td><b class=b1>{}</b> </td></tr>'.format(hw.HWInfo['PCBS_Version']) )
    ret_txt += tmp_txt
    tmp_txt = ('<tr><td>DSP Version</td><td><b class=b1>{}</b> </td></tr>'.format(hw.HWInfo['DSP_Version']) )
    ret_txt += tmp_txt
    tmp_txt = ('<tr><td>COSA Version</td><td><b class=b1>{}</b> </td></tr>'.format(hw.HWInfo['COSA_Version']) )
    ret_txt += tmp_txt
    tmp_txt = ('<tr><td>ITLA Version</td><td><b class=b1>{}</b> </td></tr>'.format(hw.HWInfo['ITLA_Version']) )
    ret_txt += tmp_txt

    # print('{:.3f} s'.format(time.time() - epoch))
    return ret_txt


# this api get module info, showing on settings page
@host_bp.route('/api/btn_get_mod_info2')
def btn_get_mod_info2():
    mod_info_all = {
        "a_mcu_ver":"---",
        "a_sub_mcu_ver":"---",
        "a_dsp_ver":"---",
        "a_running":"---",
        "a_commited":"---",
        "b_mcu_ver":"---",
        "b_sub_mcu_ver":"---",
        "b_dsp_ver":"---",
        "b_running":"---",
        "b_commited":"---",
        "pcbm_ver":"---",
        "pcbs_ver":"---",
        "dsp_ver":"---",
        "cosa_ver":"---",
        "itla_ver":"---",
        "module_config_table_ver":"---",
        "vendor_name":"---",
        "vendor_pn":"---",
        "vendor_sn":"---"
    }

    b = Broker()
    cdb = CDB(b)
    cmis = CMIS(b)
    hw = HWInfo(b)

    rlplen, rlp_chkcode, rlp = cdb.CMD0100h()
    if b.cdb_chkcode(rlp) == rlp_chkcode:
        fwStaus = rlp[0]  #136
        mod_info_all['a_running'] = (fwStaus & 0x01)
        mod_info_all['a_commited'] = ((fwStaus >> 1) & 0x01)
        mod_info_all['b_running'] = ((fwStaus >> 4) & 0x01)
        mod_info_all['b_commited'] = ((fwStaus >> 5) & 0x01)
        mod_info_all['a_mcu_ver'] = "{}.{}.{}".format( rlp[2], rlp[3], ((rlp[4] << 8) | rlp[5]) )

        sub_mcu_imageA_ver = struct.unpack('>I', rlp[6:10])[0]  #142-145
        mod_info_all['a_sub_mcu_ver'] = "{}".format( a.dot_split_style_version1(sub_mcu_imageA_ver) )

        # tmp_txt = ('<tr><td>Sub MCU Running Img </td><td> %d</td></tr>' % rlp[10])  #146
        # ret_txt += tmp_txt
        dsp_imageA_ver = struct.unpack('>I', rlp[11:15])[0]  #147-150
        mod_info_all['a_dsp_ver'] = "{}".format( a.dot_split_style_version(dsp_imageA_ver) )
        
        mod_info_all['b_mcu_ver'] = "{}.{}.{}".format( rlp[174 - 136], rlp[175 - 136], ((rlp[176 - 136] << 8) | rlp[177 - 136]) )

        sub_mcu_imageB_ver = struct.unpack(
            '>I', rlp[(178 - 136):(182 - 136)])[0]  #178-181
        mod_info_all['b_sub_mcu_ver'] = "{}".format( a.dot_split_style_version1(sub_mcu_imageB_ver) )

        dsp_imageB_ver = struct.unpack(
            '>I', rlp[(182 - 136):(186 - 136)])[0]  #182-185
        mod_info_all['b_dsp_ver'] = "{}".format( a.dot_split_style_version(dsp_imageB_ver) )
        
        b.cdb_psw()
        print(cmis.cfg_ver)
        cmis_config_ver = str(cmis.cfg_ver["Major"]) + "." + str(cmis.cfg_ver["Minor"])
        mod_info_all['module_config_table_ver'] = "{}".format( cmis_config_ver )
        
        #-------------------------------------------------------------------------------
        a.set_twi(1, 127, 0x00)
        # 129-144 16 Vendor name Vendor name (ASCII)
        vn = ''
        for i in range(129, 145):
            ret = a.get_twi(1, i).split(',')[0]  #hex
            vn = vn + chr( int('0x' + str(ret), 16) )
        mod_info_all['vendor_name'] = "{}".format( vn )

        # 148-163 16 Vendor PN Part number provided by vendor (ASCII)
        vpn = ''
        for i in range(148, 164):
            ret = a.get_twi(1, i).split(',')[0]  #hex
            vpn = vpn + chr( int('0x' + str(ret), 16) )
        mod_info_all['vendor_pn'] = "{}".format( vpn )

        # 166-181 16 Vendor SN Vendor Serial Number (ASCII)
        vsn = ''
        for i in range(166, 182):
            ret = a.get_twi(1, i).split(',')[0]  #hex
            vsn = vsn + chr( int('0x' + str(ret), 16) )

        mod_info_all['vendor_sn'] = "{}".format( vsn )
    else:
        print('Rlp check code Err...')

    # get hw info-------------------------------------------------------------
    # b.cdb_psw()
    # flash = Flash(b)
    # startAddr = 0x308000
    # sectorNo = int(startAddr / 4096)

    # readRes = b''
    # data_len = a.read_item_from_config_ini('dev','module_config_file_len')
    # if data_len == '---':
    #     pass
    # else:
    #     remaining = int(data_len)
    #     readout = 0
    #     BLOCK_SIZE = 128
    #     while remaining:
    #         if remaining >= BLOCK_SIZE:
    #             res = flash.read(startAddr+readout, BLOCK_SIZE)
    #             readRes += struct.pack('%sB'%len(res), *res)
    #             readout += BLOCK_SIZE
    #             remaining -= BLOCK_SIZE
    #         else:
    #             res = flash.read(startAddr+readout, remaining)
    #             readRes += struct.pack('%sB'%len(res), *res)
    #             readout += remaining
    #             remaining -= remaining
    #     # print(readRes)

    #     flash_data = ''.join(['%04X ' %x  for x in readRes])
    #     # print("DATA: {}".format(flash_data))
    #     fdl = flash_data.split(" ")

    #     mod_info_all['pcbm_ver'] = "{}".format( str(int('0x' + fdl[19] + fdl[18]+ fdl[17]+ fdl[16], 16)) )
    #     mod_info_all['pcbs_ver'] = "{}".format( str(int('0x' + fdl[23] + fdl[22]+ fdl[21]+ fdl[20], 16)) )
    #     mod_info_all['dsp_ver'] = "{}".format( str(int('0x' + fdl[27] + fdl[26]+ fdl[25]+ fdl[24], 16)) )
    #     mod_info_all['cosa_ver'] = "{}".format( str(int('0x' + fdl[31] + fdl[30]+ fdl[29]+ fdl[28], 16)) )
    #     mod_info_all['itla_ver'] = "{}".format( str(int('0x' + fdl[35] + fdl[34]+ fdl[33]+ fdl[32], 16)) )
    hw.load()
    mod_info_all['pcbm_ver'] = "{}".format(hw.HWInfo['PCBM_Version']) 
    mod_info_all['pcbs_ver'] = "{}".format(hw.HWInfo['PCBS_Version']) 
    mod_info_all['dsp_ver'] = "{}".format(hw.HWInfo['DSP_Version']) 
    mod_info_all['cosa_ver'] = "{}".format(hw.HWInfo['COSA_Version']) 
    mod_info_all['itla_ver'] = "{}".format(hw.HWInfo['ITLA_Version']) 

    return json.dumps(mod_info_all)


##################################################
# PIN
##################################################
gpio_1_items = [["MCU_MOD_RSTN", 20, 1], ["MCU_MOD_LPWN", 21, 1],
                ["MCU_FPGA_RSVD_4", 22, 1], ["MCU_FPGA_RSVD_5", 23, 1],
                ["P1V0_FPGA_EN", 24, 1], ["P1V8_FPGA_EN", 25, 1],
                ["P3V3_FPGA_EN", 26, 1], ["P3V3_OSFP_IN_EN", 27, 1],
                ["P3V3_LDO_EN", 28, 1], ["LED_MOD_3V3_ON", 29, 1],
                ["LED_MOD_PRSN", 30, 1], ["LED_MOD_RST", 31, 1],
                ["LED_MOD_LPWR", 32, 1], ["LED_MOD_H_INTN", 33, 1],
                ["LED_RSVD1", 34, 1], ["LED_SRVD2", 35, 1],
                ["LED_MDO_I2C_SWITCH", 36, 1], ["LED_FPGA_BREATH", 37, 1],
                ["LED_POWER_ON", 38, 1]]

gpio_2_items = [["MCU_PHY_RSTN", 39, 1], ["MCU_FPGA_RSTN", 40, 1],
                ["MCU_FPGA_PROGRAM_B", 41, 1], ["MCU_FPGA_INIT_B", 42, 1],
                ["USB_DIS_N", 43, 1], ["MCU_MEM_SPI_OE_N", 44, 1],
                ["MCU_ADC_SPI_OE_N", 45, 1], ["MCU_MEM_BUF_SPI_CS", 46, 1],
                ["MCU_ADC_BUF_SPI_CS", 47, 1],
                ["MCU_FPGA_COMM_SPI_CS_BUFFER", 48, 1],
                ["MCU_FPGA_CFG_SPI_CS_BUFFER", 49, 1],
                ["MCU_MEM_SPI_RSTN", 50, 1], ["FPGA_CLK_EN", 51, 1],
                ["MCU_SWD_SELECT", 52, 1], ["MCU_BM1", 53, 1],
                ["MCU_BM2", 54, 1], ["MCU_RSVD_4", 55, 1],
                ["MCU_MOD_SELN", 56, 1]]

gpio_3_items = [["H_INTN", 1, 0], ["H_PRSN", 2, 0], ["H_RSTN", 3, 0],
                ["H_LPWN", 4, 0], ["SW_TEST_RSVD_4", 5, 0],
                ["TEMP_ALERT_1", 6, 0], ["TEMP_ALERT_2", 7, 0],
                ["MCU_FPGA_BREATH", 8, 0], ["FPGA_MCU_DONE", 9, 0],
                ["MOD_MCU1_BM", 10, 0], ["MOD_MCU2_BM", 11, 0],
                ["DD_OSFP", 12, 0], ["H_SELN", 13, 0]]


@host_bp.route('/pin')
def pin():
    return render_template('pin.html',
                           title='Pin Settings',
                           gpio_1_items=gpio_1_items,
                           gpio_2_items=gpio_2_items,
                           gpio_3_items=gpio_3_items,
                           for_customer=for_customer)


@host_bp.route('/api/get_gpio_gpio_1')
def get_gpio_gpio_1():
    gpio_gpio_1_dict = {}
    for item in gpio_1_items:
        # print(item)
        state = a.dout_get(item[1])
        gpio_gpio_1_dict.update({item[0]: state})

    # print('-------------------------')
    # print(str(gpio_gpio_1_dict))
    # print('-------------------------')
    return json.dumps(gpio_gpio_1_dict)


@host_bp.route('/api/set_gpio_gpio_1', methods=['POST'])
def set_gpio_gpio_1():
    idx = request.form["idx"]
    val = request.form["val"]
    # idx_val = gpio_gpio_1[idx]
    for item in gpio_1_items:
        if item[0] == idx:
            idx_val = item[1]
            break
    a.dout_set(int(idx_val), int(val))
    # print("set_gpio_gpio_1... ok")
    return "set_gpio_gpio_1... ok"


@host_bp.route('/api/get_gpio_gpio_2')
def get_gpio_gpio_2():
    gpio_gpio_2_dict = {}
    for item in gpio_2_items:
        # print(item)
        state = a.dout_get(item[1])
        gpio_gpio_2_dict.update({item[0]: state})
    return json.dumps(gpio_gpio_2_dict)


@host_bp.route('/api/set_gpio_gpio_2', methods=['POST'])
def set_gpio_gpio_2():
    idx = request.form["idx"]
    val = request.form["val"]
    for item in gpio_2_items:
        if item[0] == idx:
            idx_val = item[1]
            break
    a.dout_set(int(idx_val), int(val))
    # print("set_gpio_gpio_2... ok")
    return "set_gpio_gpio_2... ok"


@host_bp.route('/api/get_gpio_gpio_3')
def get_gpio_gpio_3():
    gpio_gpio_3_dict = {}
    for item in gpio_3_items:
        # print(item)
        state = a.din_get(item[1])
        gpio_gpio_3_dict.update({item[0]: state})
    return json.dumps(gpio_gpio_3_dict)


##################################################
# LED
##################################################
led_items = [
    ['LED_POWER_ON', 'host board power on', '38'],
    ['LED_FPGA_BREATH', 'fpga working indictor', '37'],
    ['LED_MOD_I2C_SWITCH', 'i2c to module by mcu or fpga', '36'],
    ['LED_MOD_3V3_ON', 'module 3.3V power on', '29'],
    ['LED_MOD_PRSN', 'module present or not', '30'],
    ['LED_MOD_RST', 'module reset', '31'],
    ['LED_MOD_LOPWR', 'module low power', '32'],
    ['LED_MOD_H_INTN', 'H_INTN ', '33'],
    ['LED_RSVD1', 'led_rsvd1/led_rsvd2: host i2c rate indicator', '34'],
    ['LED_RSVD2', 'rate 100k: off/on, 400k: on/off, 1000k: on/on', '35'],
]


@host_bp.route('/led')
def led():
    return render_template('led.html', title='Leds', led_items=led_items,for_customer=for_customer)


@host_bp.route('/api/get_leds')
def get_leds():
    leds_dict = {}
    for item in led_items:
        state = a.dout_get(item[2])
        leds_dict.update({item[0]: state})

    return json.dumps(leds_dict)


##################################################
# ANALOG
##################################################
analog1_items = [['P3V3_OSFP_CURR_CHECK', 'A'], ['P3V3_OSFP', 'V'],
                 ['P3V3_OSFP_CON', 'V'], ['P1V0_FPGA', 'V'],
                 ['P1V8_FPGA_OSFP', 'V'], ['MODULE_CASE_TEMP1', '°C'],
                 ['P3V3_FPGA', 'V'], ['P2V5_REF', 'V'],
                 ['Temperature_1', '°C'], ['Temperature_2', '°C'],
                 ['P5V_USB_DEBUG', 'V'], ['Module_Power', 'W'],
                 ['P3V3_VccTX', 'V'], ['P3V3_VccRX', 'V']]

analog2_items = [['P3V3_OSFP', 'V']]

analog3_items = [['P3V3_OSFP_CURR_CHECK', 'A'], ['P3V3_OSFP', 'V'],
                 ['P3V3_OSFP_CON', 'V'], ['P1V0_FPGA', 'V'],
                 ['P1V8_FPGA_OSFP', 'V'], ['MODULE_CASE_TEMP1', '°C'],
                 ['P3V3_FPGA', 'V'], ['P2V5_REF', 'V'],
                 ['Temperature_1', '°C'], ['Temperature_2', '°C'],
                 ['P5V_USB_DEBUG', 'V'], ['P3V3_VccTX', 'V'],
                 ['P3V3_VccRX', 'V']]


@host_bp.route('/analog')
def analog():
    support = ""
    try:
        evb_fw = a.get_fw_ver().split(' ')[1]
        print(evb_fw)
        if int(evb_fw.split('.')[0]+evb_fw.split('.')[1]+evb_fw.split('.')[2]+evb_fw.split('.')[3]) < 20100:
            support = "hide"
    except:
        # evb_fw = -1
        pass

    # if evb_fw not in ['2.0.10.0', '2.0.10.1' ]:
    #     support = "hide"
    return render_template('analog.html',
                           title='Analog',
                           analog1_items=analog1_items,
                           analog2_items=analog2_items,
                           analog3_items=analog3_items,
                           support=support,
                           for_customer=for_customer)


analog1 = {
    'P3V3_OSFP_CURR_CHECK': 100,
    'P3V3_OSFP': 101,
    'P3V3_OSFP_CON': 102,
    'P1V0_FPGA': 103,
    'P1V8_FPGA_OSFP': 104,
    'MODULE_CASE_TEMP1': 105,
    'P3V3_FPGA': 106,
    'P2V5_REF': 107,
    'Temperature_1': 108,
    'Temperature_2': 109,
    'P5V_USB_DEBUG': 110,
    'Module_Power': 111,
    'P3V3_VccTX': 112,
    'P3V3_VccRX': 113
}

analog2 = {'P3V3_OSFP': 101}

analog3 = {
    'P3V3_OSFP_CURR_CHECK': 100,
    'P3V3_OSFP': 101,
    'P3V3_OSFP_CON': 102,
    'P1V0_FPGA': 103,
    'P1V8_FPGA_OSFP': 104,
    'MODULE_CASE_TEMP1': 105,
    'P3V3_FPGA': 106,
    'P2V5_REF': 107,
    'Temperature_1': 108,
    'Temperature_2': 109,
    'P5V_USB_DEBUG': 110,
    'P3V3_VccTX': 112,
    'P3V3_VccRX': 113
}


@host_bp.route('/api/get_analog1', methods=['POST'])
def get_analog1():
    item = request.form["item"]
    item_val = analog1[item]
    cells_val = a.ain_get(int(item_val))
    return cells_val


@host_bp.route('/api/get_analog1_all', methods=['POST'])
def get_analog1_all():
    analog1_dict = {}
    for item in analog1.keys():
        item_val = analog1[item]
        cell_val = a.ain_get(int(item_val))
        analog1_dict.update({item: cell_val.split(',')[1]})
        
    return json.dumps(analog1_dict)


@host_bp.route('/api/get_analog2', methods=['POST'])
def get_analog2():
    item = request.form["item"]
    item_val = analog2[item]
    cells_val = a.aout_get(int(item_val))
    return cells_val


@host_bp.route('/api/set_analog2', methods=['POST'])
def set_analog2():
    item = request.form["item"]
    analog2_phy_val = request.form["analog2_phy_val"]

    item_val = analog2[item]
    # turn on P3V3_OSFP_IN_EN LED
    a.dout_set(29, 1)
    time.sleep(0.1)
    a.aout_set(int(item_val), float(analog2_phy_val))
    return "set_analog2 ok"


@host_bp.route('/api/get_analog3', methods=['POST'])
def get_analog3():
    item = request.form["item"]
    item_val = analog3[item]
    cells_val = a.kb_get(int(item_val))
    return cells_val


@host_bp.route('/api/set_analog3', methods=['POST'])
def set_analog3():
    item = request.form["item"]
    analog3_k_val = request.form["analog3_k_val"]
    analog3_b_val = request.form["analog3_b_val"]
    item_val = analog3[item]
    a.kb_set(int(item_val), float(analog3_k_val), float(analog3_b_val))
    return "set_analog3 ok"


#todo ...
@host_bp.route('/api/get_analog3_vcp', methods=['POST'])
def get_analog3_vcp():
    ret = a.comm_cmdstr_getter("*vcp 102\r\n")
    return str(ret)

@host_bp.route('/api/set_analog3_vcp', methods=['POST'])
def set_analog3_vcp():
    pin_id = int(request.form["pin_id"])
    resistance = int(request.form["resistance"])
    interval = int(request.form["interval"])
    delta = int(request.form["delta"])
    a.comm_cmdstr_getter("*vcp {} {} {} {}\r\n".format(pin_id, resistance, interval, delta))
    return "set_analog3_vcp ok"

##################################################
# CONSOLE PAGE
##################################################
@host_bp.route('/console1')
def console1():
    return render_template('console.html', title='Console',for_customer=for_customer)


@host_bp.route('/api/handle_console1_init')
def handle_console1_init():
    greet = '''
    ---------------------------------------------------------------
    Welcome to HOST EVB Debug CLI
    Type '*help' to get debug command help info
    ---------------------------------------------------------------
    '''

    return greet


@host_bp.route('/api/handle_console1', methods=['POST'])
def handle_console1():
    setdefaulttimeout(200000)
    cmd_str = request.form["cmd_str"]
    # print('++++++++++++++++++')
    # print(cmd_str)
    # print('++++++++++++++++++')
    IP_ADDR = a.read_item_from_config_ini('dev', 'ip')

    tcp_client_socket = socket(AF_INET, SOCK_STREAM)

    tcp_client_socket.connect((IP_ADDR, 1000))
    init_data = tcp_client_socket.recv(2048)
    # print(init_data)

    tcp_client_socket.send(cmd_str.encode())
    time.sleep(0.5)
    recv_data = tcp_client_socket.recv(2048)

    tcp_client_socket.close()
    return recv_data.decode('gbk')

    # buf = []
    # while True:
    #     recv_data = tcp_client_socket.recv(2048)
    #     if recv_data:
    #         buf.append(str(recv_data))
    #     else:
    #         break

    # return (''.join(buf)).decode('gbk')


@host_bp.route('/api/get_product')
def get_product():
    # PRODUCT =  a.read_item_from_config_ini('dev', 'product')
    PRODUCT = a.get_product()
    IP_ADDR = a.read_item_from_config_ini('dev', 'ip')
    return PRODUCT + "," + IP_ADDR


##################################################
# Tools - Ping
##################################################
@host_bp.route('/ping')
def ping():
    return render_template('ping.html',
                           title='Auto-discovery Host Board IP Address',for_customer=for_customer)


def connect_test(tname, segment, start_ip, end_ip, delay, q):
    ip_list = ""
    for n in range(start_ip, end_ip + 1):
        time.sleep(delay)
        print("TASK: {:<10} \tSTART_IP: {:<20} \tEND_IP: {:<20}".format(tname, segment+ str(start_ip), segment+str(end_ip)))
        try:
            setdefaulttimeout(1)
            tcp_client_socket = socket(AF_INET, SOCK_STREAM)
            tcp_client_socket.connect((segment + str(n), 1000))
            tcp_client_socket.close()
            print(segment + str(n) + " : Connect OK")
            ip_list = ip_list + segment + str(
                n
            ) + "&nbsp;&nbsp;&nbsp;&nbsp;<button class='btn btn-success' onclick=connect('" + segment + str(
                n) + "')>Connect</button> <br>"
            # print("ip_list ...." + ip_list)
        except:
            # print("192.168.1." + str(n) + " : Disconnect!")
            pass
    q.put(ip_list)


@host_bp.route('/api/btn_scan_ipaddr', methods=['POST'])
def btn_scan_ipaddr():
    segment = str(request.form["segment"])
    start_ip = int(request.form["start_ip"])
    end_ip = int(request.form["end_ip"])

    epoch = time.time()
    q = Queue()
    threads = []
    for i in range(15):
        t = threading.Thread(target=connect_test,
                             args=("t" + str(i), segment, 17 * i + 1, 17 * i + 17, 1,
                                   q))
        t.start()
        threads.append(t)

    for thread in threads:
        thread.join()

    results = []
    for _ in range(15):
        results.append(q.get())

    print(results)
    print("All done!")
    print('Scan Time: {:.3f} s'.format(time.time() - epoch))

    ret_all = ""
    for ret in results:
        if len(ret) > 0:
            # return(ret)
            ret_all += ret

    if len(ret_all) > 0:
        return ret_all
    else:
        return ("Not Found Host Board IP Adreess.")


##################################################
# DASHBOARD,  demo only
##################################################
@host_bp.route('/dashboard')
def dashboard():
    return render_template('dashboard.html', title='Dashboard', for_customer=for_customer)
